package com.ifacebox.client.tools;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author znn
 */
public class SspUploadManager {
    private final OkHttpClient client;
    private final SspUploadConfig config;

    public SspUploadManager(SspUploadConfig config) {
        this.config = config;
        this.client = new OkHttpClient.Builder().build();
    }

    /**
     * 查询全部POI
     */
    public Map<String, String> queryMonitInfo() throws IOException {
        Map<String, String> params = new HashMap<>(1);
        params.put("orderId", config.getOrderId());
        Request request = new Request.Builder()
                .header("X-XSRF-TOKEN", config.getToken())
                .header("Cookie", config.getCookie())
                .post(RequestBody.create(MediaType.parse("application/json"), JSON.toJSONBytes(params)))
                .url(SspUploadConstants.UPLOAD_QUERY_MONITINFO_URL)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException(response.code() + ":" + response.message());
            }
            JSONObject object = JSON.parseObject(response.body().string());
            if (!SspUploadConstants.UPLOAD_OK.equals(object.getString(SspUploadConstants.UPLOAD_ERR_NO))) {
                throw new IOException(object.getString(SspUploadConstants.UPLOAD_ERR_MSG));
            }
            JSONObject data = object.getJSONObject("data");
            JSONArray monitInfoUnitList = data.getJSONArray("monitInfoUnitList");
            for (int i = 0; i < monitInfoUnitList.size(); i++) {
                JSONObject monitInfoUnit = monitInfoUnitList.getJSONObject(i);
                if (!config.getDate().equals(monitInfoUnit.getString("date"))) {
                    continue;
                }
                JSONArray places = monitInfoUnit.getJSONArray("place");
                Map<String, String> allPoi = new HashMap<>(places.size());
                for (int j = 0; j < places.size(); j++) {
                    JSONObject place = places.getJSONObject(j);
                    allPoi.put(place.getString("poi"), place.getString("poiId"));
                }
                return allPoi;
            }
            return null;
        }
    }

    /**
     * 查找POI
     *
     * @param poiName 名称
     * @return POI
     * @throws IOException 异常
     */
    public String searchPoi(String poiName) throws IOException {
        Map<String, String> params = new HashMap<>(3);
        params.put("date", config.getDate());
        params.put("orderId", config.getOrderId());
        params.put("poiName", poiName);
        Request request = new Request.Builder()
                .header("X-XSRF-TOKEN", config.getToken())
                .header("Cookie", config.getCookie())
                .post(RequestBody.create(MediaType.parse("application/json"), JSON.toJSONBytes(params)))
                .url(SspUploadConstants.UPLOAD_SEARCH_POI_URL)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException(response.code() + ":" + response.message());
            }
            JSONObject object = JSON.parseObject(response.body().string());
            if (!SspUploadConstants.UPLOAD_OK.equals(object.getString(SspUploadConstants.UPLOAD_ERR_NO))) {
                throw new IOException(object.getString(SspUploadConstants.UPLOAD_ERR_MSG));
            }
            JSONObject data = object.getJSONObject("data");
            JSONArray pois = data.getJSONArray("pois");
            for (int i = 0; i < pois.size(); i++) {
                JSONObject poi = pois.getJSONObject(i);
                if (poiName.equalsIgnoreCase(poi.getString("poi"))) {
                    return poi.getString("poiId");
                }
            }
            return null;
        }
    }

    /**
     * 上传文件接口
     *
     * @param file 文件
     * @return 文件地址
     * @throws IOException 异常
     */
    public String uploadFile(File file) throws IOException {
        Request request = new Request.Builder()
                .header("X-XSRF-TOKEN", config.getToken())
                .header("Cookie", config.getCookie())
                .post(new MultipartBody.Builder()
                        .setType(MultipartBody.FORM)
                        .addFormDataPart("opUser", config.getOpUser())
                        .addFormDataPart("optName", config.getOptName())
                        .addFormDataPart("logId", config.getLogId())
                        .addFormDataPart("appKey", config.getAppKey())
                        .addFormDataPart("sign", config.getSign())
                        .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("application/from-data"), file))
                        .build())
                .url(SspUploadConstants.UPLOAD_FILE_URL)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException(response.code() + ":" + response.message());
            }
            JSONObject object = JSON.parseObject(response.body().string());
            if (!SspUploadConstants.UPLOAD_OK.equals(object.getString(SspUploadConstants.UPLOAD_ERROR_CODE))) {
                throw new IOException(object.getString(SspUploadConstants.UPLOAD_ERROR_MSG));
            }
            JSONObject result = object.getJSONObject("result");
            return result.getString("url");
        }
    }

    /**
     * 上传反馈监播接口
     *
     * @param url     文件地址
     * @param placeId POI
     * @return 是否成功
     * @throws IOException 异常
     */
    public boolean uploadFeedbackImage(String url, String placeId) throws IOException {
        Map<String, String> params = new HashMap<>(4);
        params.put("date", config.getDate());
        params.put("orderId", config.getOrderId());
        params.put("placeId", placeId);
        params.put("url", url);
        Request request = new Request.Builder()
                .header("X-XSRF-TOKEN", config.getToken())
                .header("Cookie", config.getCookie())
                .post(RequestBody.create(MediaType.parse("application/json"), JSON.toJSONBytes(params)))
                .url(SspUploadConstants.UPLOAD_FEEDBACK_IMAGE_URL)
                .build();
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException(response.code() + ":" + response.message());
            }
            JSONObject object = JSON.parseObject(response.body().string());
            if (!SspUploadConstants.UPLOAD_OK.equals(object.getString(SspUploadConstants.UPLOAD_ERR_NO))) {
                throw new IOException(object.getString(SspUploadConstants.UPLOAD_ERR_MSG));
            }
            return true;
        }
    }

    /**
     * 上传
     *
     * @param file   文件
     * @param allPoi 全部POI
     * @throws IOException 异常
     */
    public void upload(File file, Map<String, String> allPoi) throws IOException {
        if (file == null || !file.isFile() || !file.exists()) {
            throw new IOException("文件不存在");
        }
        String poiName = FilenameUtils.getBaseName(file.getName());
        //Step 1.
        String placeId = null;
        if (allPoi != null && !allPoi.isEmpty()) {
            placeId = allPoi.get(poiName);
        }
        if (placeId == null || placeId.isEmpty()) {
            placeId = this.searchPoi(poiName);
        }
        if (placeId == null || placeId.isEmpty()) {
            throw new IOException("未找到POI");
        }
        //Step 2.
        String url = this.uploadFile(file);
        if (url == null || url.isEmpty()) {
            throw new IOException("上传OSS失败");
        }
        //Step 3.
        if (!this.uploadFeedbackImage(url, placeId)) {
            throw new IOException("上传失败");
        }
        FileUtils.moveFileToDirectory(file, new File(config.getFile(), "bak"), true);
    }
}
